<template>
  <div>
    <el-tabs :style="{height:initSize.height,width:initSize.width}" type="border-card">
      <el-tab-pane label="产品">
        <div v-if="initModelType" style="margin:0px 0px 10px 0px;">
          <el-tooltip content="设置模式" placement="right">
            <el-cascader
              :options="initModelOption"
              v-model="modelValue"
              size="mini"
              style="width:185px;"
              expand-trigger="hover"
              @change="modelChange"
            />
          </el-tooltip>
        </div>
        <div style="margin:0px 0px 10px 0px;">
          <el-tooltip content="自动播放" placement="left">
            <el-switch v-model="autoPlaying" style="display:inline" @change="handleAutoPlayChange"/>
          </el-tooltip>
          <el-tooltip content="设置中心" placement="right">
            <el-cascader
              :options="initRegionOption"
              v-model="regionValue"
              size="mini"
              style="width:140px;"
              expand-trigger="hover"
              @change="regionChange"
            />
          </el-tooltip>
        </div>
        <div v-if="initCaseType" style="margin:0px 0px 10px 0px;">
          <el-tooltip content="选择个例" placement="right">
            <el-select
              v-model="caseValue"
              size="mini"
              placeholder="请选择个例"
              style="width:185px"
              @change="caseChange"
            >
              <el-option
                v-for="item in initCaseOption"
                :key="item.value"
                :label="item.label"
                :value="item.value"
              />
            </el-select>
          </el-tooltip>
        </div>
        <div style="margin:0px 0px 0px 0px;">
          <select
            ref="cinradSelect"
            v-model="selected"
            :style="{height:initSize.selectedHeight,width:initSize.selectedWidth}"
            multiple
            @change="selectChange"
          >
            <option v-for="item in options" :key="item.value" :value="item.value">{{ item.label }}</option>
          </select>
        </div>
        <div style="margin:5px 0px 5px 0px;width:200px;text-align: center;">
          <el-pagination
            :current-page="currentPage"
            :total="total"
            :page-size="computedPageSize"
            small
            layout="prev, pager, next"
            @current-change="handleCurrentChange"
          />
        </div>
        <div style="width:100%;text-align:center;">
          <el-button-group>
            <el-button size="small" type="primary" @click="play">动画</el-button>
            <el-button size="small" type="info" @click="handleChangeDateRange">时段</el-button>
            <el-button size="small" type="success" @click="handleRefreshData">刷新</el-button>
          </el-button-group>
        </div>
      </el-tab-pane>
      <el-tab-pane label="配置">
        <el-collapse v-model="activeName" accordion>
          <el-collapse-item title="可见图层" name="1">
            <el-tree
              ref="tree"
              :data="initLayersVisibleOption"
              :default-checked-keys="calCheckedKeys()"
              :props="treeProps"
              show-checkbox
              node-key="id"
              @check-change="handleTreeCheckChange"
            />
          </el-collapse-item>
          <el-collapse-item title="图层透明度" name="2">
            <el-tooltip content="地理底图" placement="left">
              <el-slider
                v-model="layersOpacity[0]"
                :step="10"
                style="padding:0px 10px 0px 10px;"
                show-stops
                @change="opacityChange"
              />
            </el-tooltip>
            <el-tooltip content="雷达产品1" placement="left">
              <el-slider
                v-model="layersOpacity[1]"
                :step="10"
                style="padding:0px 10px 0px 10px;"
                show-stops
                @change="opacityChange"
              />
            </el-tooltip>
            <el-tooltip content="雷达产品2" placement="left">
              <el-slider
                v-model="layersOpacity[2]"
                :step="10"
                style="padding:0px 10px 0px 10px;"
                show-stops
                @change="opacityChange"
              />
            </el-tooltip>
            <el-tooltip content="雷达产品3" placement="left">
              <el-slider
                v-model="layersOpacity[3]"
                :step="10"
                style="padding:0px 10px 0px 10px;"
                show-stops
                @change="opacityChange"
              />
            </el-tooltip>
            <el-tooltip content="半径范围" placement="left">
              <el-slider
                v-model="layersOpacity[4]"
                :step="10"
                style="padding:0px 10px 0px 10px;"
                show-stops
                @change="opacityChange"
              />
            </el-tooltip>
            <el-tooltip content="城市边界" placement="left">
              <el-slider
                v-model="layersOpacity[5]"
                :step="10"
                style="padding:0px 10px 0px 10px;"
                show-stops
                @change="opacityChange"
              />
            </el-tooltip>
            <el-tooltip content="鼠标定位" placement="left">
              <el-slider
                v-model="layersOpacity[6]"
                :step="10"
                style="padding:0px 10px 0px 10px;"
                show-stops
                @change="opacityChange"
              />
            </el-tooltip>
            <el-tooltip content="风暴产品" placement="left">
              <el-slider
                v-model="layersOpacity[7]"
                :step="10"
                style="padding:0px 10px 0px 10px;"
                show-stops
                @change="opacityChange"
              />
            </el-tooltip>
          </el-collapse-item>
          <el-collapse-item title="属性设置" name="3">
            <div>动画间隔（毫秒）：
              <el-input v-model="during" placeholder="动画间隔" @change="handleDuringChange"/>
            </div>
            <div>动画结束等待（毫秒）：
              <el-input v-model="delay" placeholder="动画结束等待" @change="handleDelayChange"/>
            </div>
            <div>自动刷新间隔（毫秒）：
              <el-input v-model="refresh" placeholder="自动刷新间隔" @change="handleRefreshChange"/>
            </div>
            <div>雷达产品总数：
              <el-input v-model="totals" placeholder="雷达产品总数" @change="handleTotalChange"/>
            </div>
            <div>自动选择雷达产品数目：
              <el-input
                v-model="refreshSelectedSize"
                placeholder="自动选择产品数目"
                @change="handleSelectSizeChange"
              />
            </div>
          </el-collapse-item>
        </el-collapse>
      </el-tab-pane>
      <el-tab-pane label="图例">
        <img src="static/images/legend.png">
      </el-tab-pane>
    </el-tabs>
    <el-dialog
      :close-on-click-modal="false"
      :show-close="false"
      :visible.sync="centerDialogVisible"
      title="设置雷达产品雷达产品日期和时间范围"
      width="500px"
      center
    >
      <div>
        <el-date-picker
          v-model="dayRange"
          type="datetimerange"
          range-separator="至"
          start-placeholder="开始日期"
          end-placeholder="结束日期"
        />
      </div>
      <span slot="footer" class="dialog-footer">
        <el-button @click="setDayRangeDefault">默认值</el-button>
        <el-button type="primary" @click="handleDayRangeChange">确 定</el-button>
      </span>
    </el-dialog>
  </div>
</template>

<script>
import axios from 'axios'
import dayjs from 'dayjs'

import {
  Fill,
  RegularShape,
  Stroke,
  Style,
  Circle as CircleStyle
} from 'ol/style.js'
import { GeoJSON } from 'ol/format.js'

import { calCinradOption, calCinradLevel2Option } from '@/utils/cinrad'

export default {
  name: 'RadarControl',
  props: {
    logName: {
      type: String,
      default: 'RadarControl:'
    },
    initOverlayType: {
      type: Boolean,
      default: false
    },
    initModelType: {
      type: Boolean,
      default: false
    },
    initCaseType: {
      type: Boolean,
      default: true
    },
    initSize: {
      type: Object,
      default: function() {
        return {
          width: '220px',
          height: '736px',
          selectedWidth: '185px',
          selectedHeight: '480px'
        }
      }
    },
    initProductValue: {
      type: Array,
      default: function() {
        return ['Z9200', '19', '2']
      }
    },
    initRegionOption: {
      type: Array,
      default: function() {
        return this.appOptions.regionOption
      }
    },
    initRegionValue: {
      type: Array,
      default: function() {
        return ['4406', '440605']
      }
    },
    initModelValue: {
      type: Array,
      default: function() {
        return [
          this.appOptions.modelOption[0]['value'],
          this.appOptions.modelOption[0]['children'][0]['value']
        ]
      }
    },
    initModelOption: {
      type: Array,
      default: function() {
        return this.appOptions.modelOption
      }
    },
    initCaseOption: {
      type: Array,
      default: function() {
        return this.appOptions.caseOption
      }
    },
    initCaseValue: {
      type: String,
      default: function() {
        return this.appOptions.caseOption[0]['value']
      }
    },
    initLayersVisible: {
      type: Array,
      default: function() {
        return []
      }
    },
    initLayersVisibleOption: {
      type: Array,
      default: function() {
        return [
          {
            id: 0,
            label: '地理底图'
          },
          {
            id: 1,
            label: '雷达产品1'
          },
          {
            id: 2,
            label: '雷达产品2'
          },
          {
            id: 3,
            label: '雷达产品3'
          },
          {
            id: 4,
            label: '半径范围'
          },
          {
            id: 5,
            label: '城市边界'
          },
          {
            id: 6,
            label: '鼠标定位'
          },
          {
            id: 7,
            label: '风暴产品'
          }
        ]
      }
    },
    initDayRange: {
      type: Array,
      default: function() {
        return [
          dayjs('1900-01-01T00:00:00').toDate(),
          dayjs('2100-01-01T00:00:00').toDate()
        ]
      }
    },
    fill: {
      type: Object,
      default: function() {
        return new Fill({ color: 'white' })
      }
    },
    stroke: {
      type: Object,
      default: function() {
        return new Stroke({ color: 'black', width: 2 })
      }
    },
    stroke2: {
      type: Object,
      default: function() {
        return new Stroke({ color: 'black', width: 3 })
      }
    },
    bstroke: {
      type: Object,
      default: function() {
        return new Stroke({ color: 'Brown', width: 2 })
      }
    }
  },
  data() {
    return {
      stormStation: this.appOptions.defaultStormStation,
      regionValue: this.initRegionValue,
      caseValue: this.initCaseValue,
      modelValue: this.initModelValue,
      dayRange: this.initDayRange,
      total: 480,
      totals: 480,
      selected: [],
      options: [],
      activeName: '1',

      layersOpacity: this.appOptions.layerOption['layersOpacity'],

      countIndex: 0,

      pauseing: false,
      intervalid: null,
      timeoutid: null,

      autoPlaying: false,
      autoPlayPauseing: false,
      autoPlayIntervalid: null,
      autoPlayTimeoutid: null,
      autoPlayCountIndex: 0,

      refreshSelectedSize: 10,

      during: 1000,
      delay: 2000,

      refreshIntervalid: null,
      refresh: 60000,

      currentPage: 1,

      interval: null,

      treeProps: {
        children: 'children',
        label: 'label'
      },

      datetime: '2000-09-17T02:06:00Z',

      centerDialogVisible: false,

      stormStyles: {
        meso: new Style({
          fill: null,
          stroke: this.stroke2
        }),
        dc: new Style({
          fill: null,
          stroke: this.bstroke
        }),
        square: new Style({
          image: new RegularShape({
            fill: null,
            stroke: this.bstroke,
            points: 4,
            radius: 10,
            angle: Math.PI / 2
          })
        }),
        triangle: new Style({
          image: new RegularShape({
            fill: this.fill,
            stroke: this.stroke,
            points: 3,
            radius: 10,
            rotation: 1,
            angle: 0
          })
        }),
        htriangle: new Style({
          image: new RegularShape({
            fill: this.fill,
            stroke: this.bstroke,
            points: 3,
            radius: 10,
            rotation: 1,
            angle: 0
          })
        }),
        star: new Style({
          image: new RegularShape({
            fill: this.fill,
            stroke: this.stroke,
            points: 5,
            radius: 10,
            radius2: 4,
            angle: 0
          })
        }),
        cross: new Style({
          image: new RegularShape({
            fill: this.fill,
            stroke: this.stroke,
            points: 4,
            radius: 10,
            radius2: 0,
            angle: 0
          })
        }),
        circle: new Style({
          image: new CircleStyle({
            radius: 10,
            fill: null,
            stroke: this.stroke
          })
        }),
        hcircle: new Style({
          image: new CircleStyle({
            radius: 10,
            fill: null,
            stroke: this.bstroke
          })
        })
      }
    }
  },
  computed: {
    computedPageSize: function() {
      const size = Math.ceil(Math.ceil(this.total / 4) / 10) * 10
      return size
    },
    computedOffset: function() {
      return this.computedPageSize * (this.currentPage - 1)
    }
  },
  watch: {
    initProductValue: function(val) {
      if (!val) {
        return
      }
      console.debug(this.logName + 'Product Option changed: ')
      this.currentPage = 1

      // this.stop()
      // this.autoPlayStop()
      this.onRefreshData()
    }
  },
  mounted() {
    if (this.initCaseType) {
      this.dayRange[0] = dayjs(
        this.appOptions.caseOption[0]['timeRange'][0]
      ).toDate()
      this.dayRange[1] = dayjs(
        this.appOptions.caseOption[0]['timeRange'][1]
      ).toDate()
    }
    this.onRefreshData()
  },
  beforeDestroy() {
    if (this.interval) {
      window.clearInterval(this.interval)
    }
    this.stop()
    this.autoPlayStop()
  },
  methods: {
    calRestUrl: function() {
      if (
        this.initProductValue[1] === '59' ||
        this.initProductValue[1] === '60' ||
        this.initProductValue[1] === '61' ||
        this.initProductValue[1] === '300' ||
        this.initProductValue[1] === '58'
      ) {
        const vp =
          this.appOptions.restfulURL +
          '.v_' +
          this.initProductValue[1] +
          "?_filter=sid='" +
          this.initProductValue[0] +
          "'" +
          ' and elevation=' +
          this.initProductValue[2] +
          ' and starttime between ' +
          dayjs(this.dayRange[0]).format('YYYY-MM-DDTHH:mm:ss') +
          ' and ' +
          dayjs(this.dayRange[1]).format('YYYY-MM-DDTHH:mm:ss') +
          '&_limit=' +
          this.computedPageSize +
          '&_offset=' +
          this.computedOffset +
          '&_orderby=value desc&_output=json'

        return vp
      }
      const v =
        this.appOptions.restfulURL +
        ".v_ppi?_filter=sid='" +
        this.initProductValue[0] +
        "'" +
        ' and elevation=' +
        this.initProductValue[2] +
        ' and datatype=' +
        this.initProductValue[1] +
        ' and starttime between ' +
        dayjs(this.dayRange[0]).format('YYYY-MM-DDTHH:mm:ss') +
        ' and ' +
        dayjs(this.dayRange[1]).format('YYYY-MM-DDTHH:mm:ss') +
        '&_limit=' +
        this.computedPageSize +
        '&_offset=' +
        this.computedOffset +
        '&_orderby=value desc&_output=json'

      return v
    },
    calCheckedKeys() {
      if (this.initLayersVisible.length > 0) {
        return this.initLayersVisible
      }
      if (this.initOverlayType) {
        return this.appOptions.layerOption.overlayVisibleLayers
      } else {
        return this.appOptions.layerOption.defaultVisibleLayers
      }
    },
    onRefreshData() {
      const _this = this

      axios
        .get(_this.calRestUrl())
        .then(function(response) {
          _this.options = response.data
          // console.debug(_this.options)
          if (_this.options && _this.options.length > 0) {
            let _tmpSize = 0
            if (_this.options.length >= _this.refreshSelectedSize) {
              _tmpSize = _this.refreshSelectedSize
            } else {
              _tmpSize = _this.options.length
            }

            let _tmpSelected = []
            for (let i = 0; i < _tmpSize; i++) {
              _tmpSelected = _tmpSelected.concat([_this.options[i]['value']])
            }

            _this.selected = _tmpSelected
          } else {
            _this.selected = []
          }

          _this.selectChange()

          _this.interval = setInterval(() => {
            _this.$refs.cinradSelect.scrollTop = 0
            clearInterval(_this.interval)
          }, 16.7)
        })
        .catch(function(error) {
          console.error(this.logName + error)
        })
    },
    handleDayRangeChange() {
      this.centerDialogVisible = false
      if (!this.dayRange) {
        this.setDayRangeDefault()
      }
      this.onRefreshData()
    },
    handleCurrentChange(val) {
      console.debug(this.logName + 'handleCurrentChange')

      this.currentPage = val
      this.onRefreshData()
    },
    setDayRangeDefault() {
      if (this.initCaseType) {
        this.dayRange = [
          dayjs(this.appOptions.caseOption[0]['timeRange'][0]).toDate(),
          dayjs(this.appOptions.caseOption[0]['timeRange'][1]).toDate()
        ]
      } else {
        this.dayRange = this.initDayRange
      }
    },
    selectChange() {
      console.debug(this.logName + 'control-tab selectChange')

      // this.$emit('select_change', this.selected)
      if (this.selected && this.selected.length > 0) {
        this.updateCinrad(this.selected[0])
      }

      this.stop()
    },
    updateCinrad(val) {
      console.debug(this.logName + 'updateCinrad')
      this.datetime = val
      const _tmp = this.$refs.tree.getCheckedKeys()
      let _featuresLayerVisible = false
      if (_tmp && _tmp.length > 0) {
        for (let i = 0; i < _tmp.length; i++) {
          if (_tmp[i] === 7) {
            _featuresLayerVisible = true
          }
        }
      }
      if (_featuresLayerVisible) {
        this.getFeatures()
      }
      console.debug('update_cinrad')
      this.$emit('update_cinrad', [this.initProductValue, val])
    },
    regionChange: function(val) {
      console.debug(this.logName + 'regionChange:' + val)
      this.$emit('region_change', val)
    },
    modelChange: function(val) {
      console.debug(this.logName + 'modelChange:' + val)
      const _tmp = calCinradLevel2Option(val, this.appOptions.modelOption)

      this.$emit('model_change', _tmp.model)
    },
    caseChange: function(val) {
      console.debug(this.logName + 'caseChange:' + val)

      const _tmp = calCinradOption(val, this.appOptions.caseOption)

      this.dayRange[0] = dayjs(_tmp['timeRange'][0]).toDate()
      this.dayRange[1] = dayjs(_tmp['timeRange'][1]).toDate()

      this.onRefreshData()

      this.$emit('case_change', _tmp)
    },
    getFeatures() {
      const _this = this
      let features = []
      // let features59 = []
      let features60 = []
      let features61 = []
      /**
      axios
        .get(
          _this.appOptions.wfsRadarURL +
            'v_59&cql_filter=starttime=' +
            _this.datetime
        )
        .then(function(response) {
          // console.log(response.data)
          if (response.data != null) {
            features59 = new GeoJSON().readFeatures(response.data)
            for (let i = 0; i < features59.length; i++) {
              // console.debug(Number(features59[i]['values_']['prob']))
              if (Number(features59[i]['values_']['prob']) >= 70) {
                features59[i].setStyle(_this.stormStyles['htriangle'])
              } else {
                features59[i].setStyle(_this.stormStyles['triangle'])
              }
            }
          }
          */
      axios
        .get(
          _this.appOptions.wfsRadarURL +
            'v_60&cql_filter=starttime=' +
            _this.datetime +
            " and sid='" +
            _this.appOptions.defaultStormStation +
            "'"
        )
        .then(function(response) {
          // console.log(response.data)
          if (response.data != null) {
            features60 = new GeoJSON().readFeatures(response.data)
            for (let i = 0; i < features60.length; i++) {
              if (features60[i]['values_']['stormtype'] === 'MESO') {
                features60[i].setStyle(_this.stormStyles['meso'])
              } else {
                features60[i].setStyle(_this.stormStyles['dc'])
              }
            }
          }
          axios
            .get(
              _this.appOptions.wfsRadarURL +
                'v_61&cql_filter=starttime=' +
                _this.datetime +
                " and sid='" +
                _this.appOptions.defaultStormStation +
                "'"
            )
            .then(function(response) {
              // console.log(response.data)
              if (response.data != null) {
                features61 = new GeoJSON().readFeatures(response.data)
                for (let i = 0; i < features61.length; i++) {
                  features61[i].setStyle(_this.stormStyles['triangle'])
                }
              }
              features = [].concat(features60, features61)

              _this.$emit('update_features', features)
            })
        })
    },
    handleChangeDateRange() {
      this.autoPlayStop()
      this.autoPlaying = false
      this.centerDialogVisible = true
    },
    handleRefreshData() {
      this.stop()
      this.autoPlayStop()
      this.autoPlaying = false
      this.onRefreshData()
    },
    handleAutoPlayChange(val) {
      this.onRefreshData()
      if (val) {
        this.autoPlay()
      } else {
        this.autoPlayStop()
      }
    },
    stop() {
      const _this = this
      if (_this.intervalid) {
        window.clearInterval(_this.intervalid)
        _this.intervalid = null
      }
      if (_this.timeoutid) {
        window.clearTimeout(_this.timeoutid)
        _this.timeoutid = null
      }
      _this.pauseing = false
      _this.countIndex = 0
    },
    pause() {
      const _this = this
      _this.pauseing = true
      _this.timeoutid = window.setTimeout(function() {
        _this.pauseing = false
      }, _this.delay)
    },
    play: function() {
      const _this = this
      _this.stop()
      _this.autoPlayStop()
      _this.autoPlaying = false
      console.debug(_this.logName + 'play:' + _this.selected.length)
      if (_this.selected && _this.selected.length > 1) {
        _this.intervalid = window.setInterval(function() {
          if (_this.countIndex >= _this.selected.length) {
            _this.countIndex = _this.countIndex - _this.selected.length
            _this.pause()
          }
          if (!_this.pauseing) {
            _this.countIndex = _this.countIndex + 1

            const _tmpTime =
              _this.selected[_this.selected.length - _this.countIndex]

            console.debug(_tmpTime)
            _this.updateCinrad(_tmpTime)
          }
        }, _this.during)
      }
    },
    autoPlayStop() {
      const _this = this
      if (_this.autoPlayIntervalid) {
        window.clearInterval(_this.autoPlayIntervalid)
        _this.autoPlayIntervalid = null
      }
      if (_this.autoPlayTimeoutid) {
        window.clearTimeout(_this.autoPlayTimeoutid)
        _this.autoPlayTimeoutid = null
      }
      if (_this.refreshIntervalid) {
        window.clearTimeout(_this.refreshIntervalid)
        _this.refreshIntervalid = null
      }
      _this.autoPlayPauseing = false
      _this.autoPlayCountIndex = 0
    },
    autoPlayPause() {
      const _this = this
      _this.autoPlayPauseing = true
      _this.autoPlayTimeoutid = window.setTimeout(function() {
        _this.autoPlayPauseing = false
      }, _this.delay)
    },
    autoPlay: function() {
      const _this = this
      _this.stop()
      _this.autoPlayStop()
      console.debug(this.logName + 'autoPlay:' + _this.selected.length)
      if (_this.selected && _this.selected.length > 1) {
        _this.autoPlayIntervalid = window.setInterval(function() {
          if (_this.autoPlayCountIndex >= _this.selected.length) {
            _this.autoPlayCountIndex =
              _this.autoPlayCountIndex - _this.selected.length
            _this.autoPlayPause()
          }
          if (!_this.autoPlayPauseing) {
            _this.autoPlayCountIndex = _this.autoPlayCountIndex + 1

            const _tmpTime =
              _this.selected[_this.selected.length - _this.autoPlayCountIndex]

            console.debug(_tmpTime)
            _this.updateCinrad(_tmpTime)
          }
        }, _this.during)
      }
      _this.refreshIntervalid = window.setInterval(function() {
        console.debug(_this.logName + 'refreshIntervalid')
        _this.onRefreshData()
        _this.autoPlayCountIndex = 0
      }, _this.refresh)
    },
    handleTreeCheckChange(val1, val2) {
      console.debug(
        this.logName +
          'handleTreeCheckChange:' +
          this.$refs.tree.getCheckedKeys()
      )
      this.$emit('layers_visible_change', this.$refs.tree.getCheckedKeys())
      this.updateCinrad(this.selected[0])
    },
    opacityChange(val) {
      console.debug(this.layersOpacity)
      this.$emit('opacity_change', this.layersOpacity)
    },
    handleDuringChange(val) {
      if (!val) {
        this.during = 1000
      }
      this.stop()
      this.autoPlayStop()
      this.onRefreshData()
    },
    handleDelayChange(val) {
      if (!val) {
        this.delay = 2000
      }
      this.stop()
      this.autoPlayStop()
      this.onRefreshData()
    },
    handleRefreshChange(val) {
      if (!val) {
        this.refresh = 60000
      }
      this.stop()
      this.autoPlayStop()
      this.onRefreshData()
    },
    handleTotalChange(val) {
      console.debug(val)
      if (!val || val < 10) {
        this.totals = 480
      }
      this.total = Number(this.totals)
      this.stop()
      this.autoPlayStop()
      this.onRefreshData()
    },
    handleSelectSizeChange(val) {
      if (!val) {
        this.refreshSelectedSize = 10
      }
      this.stop()
      this.autoPlayStop()
      this.onRefreshData()
    }
  }
}
</script>
